查看原文
其他

原创 | Thinkphp5.1应用初探

Sentiment SecIN技术平台 2024-05-25

点击蓝字




关注我们


直接审计tp的话应该会很有难度,不妨先了解一些tp内置规则和用法,便于在后续的审计中更好的理解代码含义。

源码下载链接:
https://github.com/heyguojing/thinkphp5.1

ThinkPHP5.1 开发手册:
https://www.kancloud.cn/manual/thinkphp5_1/353951

安装

没有composer可以去下载,傻瓜式安装即可Composer (getcomposer.org)

https://getcomposer.org/download/

使用composer安装

composer create-project topthink/think tp
启动服务

cd tpphp think run

然后就可以在浏览器中访问

http://localhost:8000
搭建成功

目录结构

www WEB部署目录(或者子目录)application 应用目录 common 公共模块目录(可以更改) module_name 模块目录 common.php 模块函数文件 controller 控制器目录 model 模型目录 view 视图目录 ... 更多类库目录 command.php 命令行定义文件 common.php 公共函数文件 tags.php 应用行为扩展定义文件
config 应用配置目录 module_name 模块配置目录 database.php 数据库配置 cache 缓存配置 ... app.php 应用配置 cache.php 缓存配置 cookie.php Cookie配置 database.php 数据库配置 log.php 日志配置 session.php Session配置 template.php 模板引擎配置 trace.php Trace配置
route 路由定义目录 route.php 路由定义 ... 更多
public WEB目录(对外访问目录) index.php 入口文件 router.php 快速测试文件 .htaccess 用于apache的重写
thinkphp 框架系统目录 lang 语言文件目录 library 框架类库目录 think Think类库包目录 traits 系统Trait目录 tpl 系统模板目录 base.php 基础定义文件 console.php 控制台入口文件 convention.php 框架惯例配置文件 helper.php 助手函数文件 phpunit.xml phpunit配置文件 start.php 框架入口文件
extend 扩展类库目录runtime 应用的运行时目录(可写,可定制)vendor 第三方类库目录(Composer依赖库)build.php 自动生成定义文件(参考)composer.json composer 定义文件LICENSE.txt 授权说明文件README.md README 文件think                 命令行入口文件


命名规范

ThinkPHP5遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范:

目录和文件

  • 目录不强制规范,驼峰和小写+下划线模式均支持;

  • 类库、函数文件统一以.php为后缀;

  • 类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致;

  • 类名和类文件名保持一致,统一采用驼峰法命名(首字母大写);


函数和类、属性命名

  • 类的命名采用驼峰法,并且首字母大写,例如 User、UserType,默认不需要添加后缀,例如UserController应该直接命名为User;

  • 函数的命名使用小写字母和下划线(小写字母开头)的方式,例如 get_client_ip;

  • 方法的命名使用驼峰法,并且首字母小写,例如 getUserName;

  • 属性的命名使用驼峰法,并且首字母小写,例如 tableName、instance;

  • 以双下划线“__”打头的函数或方法作为魔法方法,例如 __call 和 __autoload;


常量和配置

  • 常量以大写字母和下划线命名,例如 APP_PATH和 THINK_PATH;

  • 配置参数以小写字母和下划线命名,例如 url_route_on 和url_convert;


数据表和字段

  • 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 think_user 表和 user_name字段,不建议使用驼峰和中文作为数据表字段命名。


URL解析模式

http://localhost/index.php/模块/控制器/操作/参数/值

如果使用的是伪静态,就不必加上

/thinkphp/tp5/public/index.php/了

http://127.0.0.1:8000/index/index/hello/name/Sentiment

在url地址栏里面如果不写模块、控制器和操作名,默认访问的就是index模块下面的index控制器下面的index操作,可以在config/app.php文件中进行修改。

控制器定义

控制器,即 controller,控制器文件存放在 controller 目录下

类名和文件名大小写保持一致,采用驼峰法()

如果类名是 双字母组合,比如 class HelloWorld,url 访问时必须用:hello_world;

想要原样方式访问 URL,则需要关闭配置文件中的自动转换

‘url_convert’ => false;

在Test模块下,定义一个HelloWorld控制器,test操作

<?phpnamespace app\test\controller;
class HelloWorld{ public function test(){ return 'hello_world!!!!!'; }}

访问HelloWorld控制器时,就必须以hello_world形式才行

渲染输出

使用 view 输出模板

方法同名文件

tp中内置了一个view()方法,它可以找到同模块下的view/控制器同名文件夹(这里就是test)/与方法同名的文件.html(定义的是show方法,所以会自动追踪到show.html)

根据url解析模式,直接访问test模块,test控制器,show操作

不同名文件

若不是方法同名.html,在view()中加上对应的html文件名即可(`view/同名控制器/参数同名.html)


数据库操作

数据库配置在config/database.php下,数据库操作分为两种类型:DB类,模型类

这里先设置下数据库名,用户名,密码,表前缀可选我这里填的think_

下一步就是创建数据库了,在think数据库的think_data表下创建三个字段

DB类

原生查询

支持query(查询操作)和execute(写入操作)方法

添加数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::execute('insert into think_data (id,name,status) values(1,"Sentiment",1)'); return dump($resault); }}
访问方法

执行成功

再插入一条

$resault = Db::execute('insert into think_data (id,name,status) values(1,"Tana",1)');

更新数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::execute('update think_data set id=2 where name="Sentiment"'); return dump($resault); }}

删除数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::execute('delete from think_data where name ="Tana"'); return dump($resault); }}

查询数据

query用于查询,默认情况下返回数组集,execute方法的返回值是影响的行数

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::query('select * from think_data'); return dump($resault); }}

查询构造器


添加数据

通过insert语句添加数据,如果设置了表前缀(prefix)则可以使用name(表后缀),若没设置则需全名即:table(think_data),也可应inserAll插入多条数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $data=['id' => 1, 'name' => 'Sentiment','status'=>1]; $resault = Db::name('data')->insert($data); return dump($resault); }}

更新数据

可以用update语句,也可以是tp封装的setField,同时若需要字段自增/自减也可以用setInc/setDec

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::name('data')->where('name', "Sentiment")->update(['id' => '2']); //tp5封装函数 $resault = Db::name('data')->where('name', "Sentiment")->setField('id',2); //不给第二个参数,默认为1 $resault = Db::name('data')->where('name', "Sentiment")->setInc('id'); //自减2 $resault = Db::name('data')->where('name', "Sentiment")->setDec('id',2); return dump($resault); }}

删除数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::name('data')->where('name', "Tana")->delete(); return dump($resault); }}

查询数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $resault = Db::name('data')->select(); return dump($resault); }}

助手函数

用 $db=\db('data');代替Db::name('data'),db 助手函数默认会每次重新连接数据库,因此应当尽量避免多次调用。

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $db=\db('data'); $resault=$db->select(); return dump($resault); }}

链式操作

数据库提供的链式操作方法,可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作(原生查询不支持链式操作)。

链式操作不分先后,只要在查询方法(select()、find())前调用就行

Db::name('data') -> where('status',1) -> order('create_time') -> limit(10) -> select();

链式操作查询方法

连贯操作作用
支持的参数类型

where

用于AND查询

字符串、数组和对象

whereOr

用于OR查询

字符串、数组和对象

wheretime

用于时间日期的快捷查询

字符串

table

用于定义要操作的数据表名称

字符串和数组

alias

用于给当前数据表定义别名

字符串

field

用于定义要查询的字段(支持字段排除)

字符串和数组

order

用于对结果排序

字符串和数组

limit

用于限制查询结果数量

字符串和数字

page

用于查询分页(内部会转换成limit)

字符串和数字

group

用于对查询的group支持

字符串

having

用于对查询的having支持

字符串

join

用于对查询的join支持

字符串和数组

union

用于对查询的union支持

字符串、数组和对象

view

用于视图查询

字符串、数组

distinct

用于查询的distinct支持

布尔值

lock

用于数据库的锁机制

布尔值

cache

用于查询缓存

支持多个参数

relation

用于关联查询

字符串

with

用于关联预载入

字符串、数组

bind

用于数据绑定操作

数组或多个参数

comment

用于SQL注释

字符串

force

用于数据集的强制索引

字符串

master

用于设置主服务器读取数据

布尔值

strict

用于设置是否严格检测字段名是否存在

布尔值

sequence

用于设置Pgsql的自增序列名

字符串

failException

用于设置没有查询到数据是否抛出异常

布尔值

partition

用于设置分表信息

数组 字符串

查询表达式

select()用于查询数据集,查询成功则返回一个二维数组,如果没有满足条件则返回空数组

find()用于查找满足条件的第一个记录,如果查询成功,返回一个以为数组,如果失败则返回null

表达式
含义快捷查询方法

=

等于


<>

不等于


>

大于


>=

大于等于


<

小于


<=

小于等于


[NOT] LIKE

模糊查询

whereLike/whereNotLike

[NOT] BETWEEN

(不在)区间查询

whereBetween/whereNotBetween

[NOT] IN

(不在)IN 查询

whereIn/whereNotIn

[NOT] NULL

查询字段是否(不)是NULL

whereNull/whereNotNull

[NOT] EXISTS

EXISTS查询

whereExists/whereNotExists

[NOT] REGEXP

正则(不)匹配查询(仅支持Mysql)


[NOT] BETWEEM TIME

时间区间比较

whereBetweenTime

> TIME

大于某个时间

whereTime

< TIME

小于某个时间

whereTime

>= TIME

大于等于某个时间

whereTime

<= TIME

小于等于某个时间

whereTime

EXP

表达式查询,支持SQL语法

whereExp

比较查询

查询id不等于1的数据

<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ $result = Db::name('data')->where("id",'<>','1')->select(); return dump($result); }}
区间查询
<?php
namespace app\test\controller;use think\Db;
class Data{ public function index(){ //模糊查询name中带n的数据 //$result = Db::name('data')->where("name",'like','%n%')->select(); //区间查询id为1-3的数据 $result = Db::name('data')->where("id",'BETWEEN','[1,3]')->select(); return dump($result); }}
时间查询

查询2022-5-11以后的数据

$result = Db::name('data')->where("create_time",'> TIME','2022-5-11')->select();
其它查询

查询id=1或3的数据

$result = Db::name('data')->where("id",'EXP','IN (1,3)')->select();$result = Db::name('data')->whereExp("id",'IN (1,3)')->select();
模型类

在模型中除了可以调用数据库类的方法之外(换句话说,数据库的所有查询方法模型中都可以支持),可以定义自己的方法,所以也可以把模型看成是数据库的增强版。

模型定义

先建个think_user表

在test/model下建个think_user模型User,这里的模型名=表名,所以必须叫User

新增数据

建好模型就开始数据库操作了,use部分用到的就是刚刚定义的User,但为了不与控制器重名加了个as,这里用了两种方式添加数据

<?phpnamespace app\test\controller;use app\test\model\User as UserModel;
class User{ public function insert(){// $user = new UserModel();// $user->id=1;// $user->name = 'Sentiment';// $user->email = 'Sentiment@qq.com';// $user->birthday=strtotime('2001-12-7');// $user->save(); //数组形式自定义 $user['id']=2; $user['name']='Tana'; $user['email']='Tana@qq.com'; $user['birthday']=strtotime('2000-1-1'); UserModel::create($user);
}
}

访问test/user/insert,执行成功(注:这里定义了四个字段,所以在insert时候必须都加上,一开始以为会自动创建id就没加,结果一直没成功)

批量添加

也可以通过saveAll,批量新增

public function insertList(){ $user = new UserModel(); $list=[ ['id'=>'3','name'=>'Mumu','email'=>'Mumu@qq.com','birthday'=>strtotime('2002-1-1')], ['id'=>'4','name'=>'Shelter','email'=>'Shelter@qq.com','birthday'=>strtotime('2003-1-1')] ]; if($user->saveAll($list)){ return 'Success'; }else{ return 'faild'; }}

更新数据

查找并更新

get获取id=1的数据

public function update(){ $user = UserModel::get(1); $user->name='Mumu'; $user->email='Mumu@qq.com'; $user->birthday=strtotime('2002-1-1'); $user->save(); #dump($user);}
直接更新数据

$user = new UserModel();$user->save(['name'=>'Shelter','email'=>'Shelter@qq.com'],['id'=>1]);
批量更新
$user = new UserModel();$list=[ ['id'=>'3','name'=>'Mumu','email'=>'Mumu@qq.com','birthday'=>strtotime('2002-1-1')], ['id'=>'4','name'=>'Shelter','email'=>'Shelter@qq.com','birthday'=>strtotime('2003-1-1')]];

通过数据库类更新

$user = new UserModel();$user->where('id',1)->update(['name'=>'Sentiment']);//包括主键的话也可以用下边这种方法//$user->update(['id'=>1,'name'=>'Tana']);

静态方法

UserModel::where('id',1)->update(['name'=>'Sentiment']);//包括主键的话也可以用下边这种方法//UserModel::update(['id'=>1,'name'=>'Tana']);
查询数据

查询单个数据

//获取单个数据$user=UserModel::get(1);echo $user->name;
//使用数组查询$user=UserModel::get(1);echo $user->email;
//实例化模型后查询$user = new UserModel();$result = $user -> where('name','Sentiment')->find();echo $result->name;

查询多个数据

// 获取多个数据//$list=UserModel::all('1,2');// 数组形式//$list=UserModel::all([1,2]);//foreach ($list as $key=>$value){// echo $value->name;// }
// 实例化模型后查询$user = new UserModel();echo $user->where('id',1)->limit(2)->order('birthday','desc')->select();

删除数据

//删除当前模型$user = UserModel::get(1);$user->delete();
//根据主键删除UserModel::destroy(1);//也可以删除多个UserModel::destroy('1,2');UserModel::destroy([1,2]);
//条件删除UserModel::destroy(['id'=>1]);UserModel::where('id','>',0)->delete();


视图

视图功能由\think\View类配合视图驱动(也即模板引擎驱动)类一起完成,目前的内置模板引擎包含PHP原生模板和Think模板引擎。

渲染模板最常用的是控制器类在继承系统控制器基类(\think\Controller)后调用fetch方法,调用格式:

fetch('[模板文件]'[,'模板变量(数组)'])
常用方法:
方法说明

fetch

渲染模板输出

display

渲染内容输出

assign

模板变量赋值

engine

初始化模板引擎


视图渲染

不给任何参数情况下默认返回,当前文件/view/控制器名/方法名.html

<?phpnamespace app\test\controller;use think\Controller;
class See extends Controller{ public function index(){ // 自动定位 //return $this->fetch(); //test/view/see/index.html
// 指定模板 //return $this->fetch('test'); //test/view/see/test.html
//指定目录 //return $this->fetch('test/show'); //test/view/test/show.html
// 指定模块下的模板,适用于多模块 //return $this->fetch('admin@public/test'); //admin/view/public/test.html
//view_path 下的模块 //return $this->fetch('/Sentiment'); //test/view/Sentiment.html
// 如果没有继承 Controller 模块的话,可以使用助手函数 view() 方法,具体使用方法同上 return view(); //test/view/see/index.html }}

视图赋值

视图赋值主要通过assign函数

assign赋值

//test/controller/Assign.php
<?phpnamespace app\test\controller;use think\Controller;
class Assign extends Controller{ public function index(){ //模板变量赋值 $name='Sentiment'; $age=18;// $this->assign('name',$name);// $this->assign('age',$age); //也可以通过数组赋值 $this->assign([ 'name'=>$name, 'age'=>$age, ]); return $this->fetch(); }
}

想输出变量直接{$name}即可

/test/view/assign/index.html

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Assign Test</title></head><body>this is assign/index.html</br>{$name}</br>{$age}</body></html>

访问/test/assign/index方法 成功返回body内容及变量值

fetch赋值

return $this->fetch('index',['name'=>$name,'age'=>$age]);
助手函数

return view('index',['name'=>$name,'age'=>$age]);

display方法

return $this->display('{$name} {$age}',['name'=>'Tana','age'=>$age]);


视图过滤

filter()函数过滤

<?phpnamespace app\test\controller;use think\Controller;
class Assign extends Controller{ public function index(){ //视图过滤 $this->assign(['name' => 'Sentiment6', 'age'=>186]); return $this->filter(function ($content) { return str_replace('6', '<br>', $content); })->fetch(); }}

将6替换成了<br/>

初始化中全局过滤

<?phpnamespace app\test\controller;use think\Controller;
class Assign extends Controller{ public function index(){ $this->assign(['name' => 'Sentiment6', 'age'=>186]); return $this->fetch(); } public function initialize(){ return $this->filter(function ($content) { return str_replace('6', '<br>', $content); }); }
}

助手函数

<?phpnamespace app\test\controller;use think\Controller;
class Assign extends Controller{ public function index(){ $this->assign(['name' => 'Sentiment6', 'age'=>186]); return view('index')->filter( function ($content) { return str_replace('6', '<br>', $content); } ); }
}


模板

变量输出

普通输出方式

//test/controller/Assign.php<?phpnamespace app\test\controller;use think\Controller;
class Assign extends Controller{ public function index(){ $this->assign('name', 'Sentiment'); return $this->fetch(); }}

模板

//test/view/assign/index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Assign Test</title></head><body>this is assign/index.html</br>Hello {$name}</body></html>

系统变量输出

{$Think.server.script_name} // 输出$_SERVER['SCRIPT_NAME']变量{$Think.session.user_id} // 输出$_SESSION['user_id']变量{$Think.get.page} // 输出$_GET['page']变量{$Think.cookie.name}  // 输出$_COOKIE['name']变量

在index.html中加上{$Think.server.script_name},即可输出对应的script_name值

常量输出

{$Think.const.PHP_VERSION}{$Think.PHP_VERSION}

在Assign.php中定义个常量

define('AAA','this is define');

在index.html加上

{$Think.AAA}

配置输出

{$Think.config.default_module}{$Think.config.default_controller}
语言配置

{$Think.lang.page_error}{$Think.lang.var_error}

使用函数

过滤方法
描述

date

日期格式化(支持各种时间类型)

format

字符串格式化

upper

转换为大写

lower

转换为小写

first

输出数组的第一个元素

last

输出数组的最后一个元素

default

默认值

raw

不使用(默认)转义

Assign.php

<?phpnamespace app\test\controller;use think\Controller;define('AAA','this is define');class Assign extends Controller{ public function index(){ $name='Sentiment'; $time=time(); $this->assign('name',$name); $this->assign('time',$time); return $this->fetch(); }}

index.html

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Assign Test</title></head><body>this is assign/index.html<br> {$name|md5}<br> //md5('Sentiment'){$name|upper|substr=0,3}<br> //substr(upper('Sentiment')){$time|date='Y-m-d H:i'}<br> //时间</body></html>

原样输出

加上{literal}后,{$name}就不会被解析,而是原样输出

{literal} Hello,{$name}!{/literal}

模板输出

单行注释

格式:

{/* 注释内容 */ } 或 {// 注释内容 }
例如

{// 这是模板注释内容 }
注:{和注释标记之间不能有空格。

多行注释,支持多行注释,例如:

{/* 这是模板注释内容*/ }
模板注释支持多行,模板注释在生成编译缓存文件后会自动删除,这一点和Html的注释不同。

模板布局

全局配置方式

在template.php中,开启layout_on参数(默认不开启),并且设置布局入口文件名layout_name(默认为layout)。(assign为我的view目录下的文件,根据自己情况修改或不加)

'layout_on' => true,'layout_name'   =>  'assign/layout',

在不开启layout_on布局模板之前,会直接渲染 application/test/view/assign/index.html 模板文件,开启之后,首先会渲染

application/test/view/layout.html模板,布局模板的写法和其他模板的写法类似,本身也可以支持所有的模板标签以及包含文件,区别在于有一个特定的输出替换变量{__CONTENT__},例如,下面是一个典型的layout.html模板的写法:

{include file="public/header" /} {__CONTENT__}{include file="public/footer" /}

在view/assign/下,新建layout.html,包含的是see/index.html

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>a Test</title></head><body> {include file="see/index" /}<br> {__CONTENT__} {include file="see/index" /}<br></body></html>

原本的assign/index.html把html标签去掉即可

{$name|md5}<br>{$name|upper|substr=0,3}<br>{$time|date='Y-m-d H:i'}<br>

访问后{CONTENT}部分自动替换成了index.html内容

这里的{CONTENT}是默认的也可以通过修改配置来定义

'layout_item' => '{__REPLACE__}'

这里通过配置文件定义的是全局配置,若某个文件不想使用该配置,则可以在html文件中加入{__NOLAYOUT__}来取消本文件的全局配置

{__NOLAYOUT__} //加上后就不会被解析了{$name|md5}<br>{$name|upper|substr=0,3}<br>{$time|date='Y-m-d H:i'}<br>

模板标签方式

直接在模板文件中指定布局模板即可(前边的layout_on设置需要关闭)

{//__NOLAYOUT__}{layout name="assign/layout" /}{$name|md5}<br>{$name|upper|substr=0,3}<br>{$time|date='Y-m-d H:i'}<br>

若需要使用其他模板布局(假设要用lay.html),直接修改标签即可

{//__NOLAYOUT__}{layout name="assign/lay" /}{$name|md5}<br>{$name|upper|substr=0,3}<br>{$time|date='Y-m-d H:i'}<br>

动态布局

也不需要设置layout_on,加上$this->view->engine->layout(true);即可

<?phpnamespace app\test\controller;use think\Controller;define('AAA','this is define');class Assign extends Controller{ public function index(){ $name='Sentiment'; $time=time(); $this->assign('name',$name); $this->assign('time',$time); $this->view->engine->layout(true); //在这里在这里 return $this->fetch(); }}

模板继承

通过{block} {/block}标签,实现继承

在view/assign/下,新建base.html

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>base</title></head><body> {block name="header"} <div style= "width:10%; height:30px; background-color:yellow;">this is header</div> {/block}<br> {block name="footer"} <div style= "width:10%; height:30px; background-color:green;">this is footer</div> {/block}<br></body></html>

view/assign/index.html

通过extend继承{extend name="assign/base" /}

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>index</title></head><body> {extend name="assign/base" /}
</body></html>

如果在子类中实现了与父类中同样的模板,则以子类中的内容显示,若此时想同时显示父类中的内容则可以通过{block}实现

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>index</title></head><body> {extend name="assign/base" /} {block name="header"}{__block__} //在这里 在这里 <div style= "width:10%; height:30px; background-color:red;">this is header</div> {/block}<br> {block name="footer"} <div style= "width:10%; height:30px; background-color:blue;">this is footer</div> {/block}<br></body></html>

包含文件

在模板布局中已经用到过了就不多解释了

{include file="see/index" /}

内置标签

标签名
作用包含属性

include

包含外部模板文件(闭合)

file

load

导入资源文件(闭合 包括js css import别名)

file,href,type,value,basepath

volist

循环数组数据输出

name,id,offset,length,key,mod

foreach

数组或对象遍历输出

name,item,key

for

For循环数据输出

name,from,to,before,step

switch

分支判断输出

name

case

分支判断输出(必须和switch配套使用)

value,break

default

默认情况输出(闭合 必须和switch配套使用)

compare

比较输出(包括eq neq lt gt egt elt heq nheq等别名)

name,value,type

range

范围判断输出(包括in notin between notbetween别名)

name,value,type

present

判断是否赋值

name

notpresent

判断是否尚未赋值

name

empty

判断数据是否为空

name

notempty

判断数据是否不为空

name

defined

判断常量是否定义

name

notdefined

判断常量是否未定义

name

define

常量定义(闭合)

name,value

assign

变量赋值(闭合)

name,value

if

条件判断输出

condition

elseif

条件判断输出(闭合 必须和if标签配套使用)

condition

else

条件不成立输出(闭合 可用于其他标签)

php

使用php代码

volist

这里以数据库内容举例,模板类获取数据库所有内容(数据库—>模板类有说过)

<?phpnamespace app\test\controller;use think\Controller;use app\test\model\User as UserModel;
class Assign extends Controller{ public function index(){ $name=UserModel::all(); $this->assign('name',$name); return $this->fetch(); }}

assign/index.html

"name"为assign的值,根据变量进行修改

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>index</title></head><body> {volist name="name" id="vo"} {$vo.id}====>{$vo.name}<br/> {/volist}</body></html>

可以加上offset="0" length="1",定义获取数据的个数

{volist name="name" id="vo" offset="0" length="1"} {$vo.id}====>{$vo.name}<br/>{/volist}

foreach

实现结果同上

{foreach $name as $vo} {$vo.id}====>{$vo.name}<br/>{/foreach}

for

{for start="开始值" end="结束值" comparison="用于比较,默认值是<" step="步长" name="循环变量名"}{/for}

循环输出1-10

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>index</title></head><body> {for start="1" end="10"} {$i} {/for}</body></html>

php

执行php语句

{php} echo 'hi Sentiment';{/php}

路由

静态

Route::get('unserialize', 'unserialize/unserialize');

访问unserialize后,便会自动跳转到

unserialize/unserialize界面

动态

Route::get('route/:id','test/Index/index');

index.php

<?phpnamespace app\test\controller;use think\facade\Request;
class Index{ public function index(){ dump(Request::route()); }}

id为我们动态输入的值,修改id后返回信息也会动态变化

请求

请求对象

1.当控制器继承了控制器基类时,会自动被注入 Request 请求对象的功能

<?phpnamespace app\test\controller;use think\Controller;class Index extends Controller{ public function index(){ return $this->request->param('name'); }}


2.不继承控制器基类(操作方法注入)

无论是否继承系统的控制器基类,都可以使用操作方法注入。

<?phpnamespace app\test\controller;use think\Request;
class Index { public function index(Request $request){ return $request->param('name'); }}

跟1传参方式一样

3、构造方法注入

<?phpnamespace app\test\controller;use think\Request;
class Index { public function __construct(Request $request){ $this->request = $request; } public function index(){ return $this->request->param('name'); }}

4、Facade调用(无依赖注入)

在没有使用依赖注入的场合,可以通过Facade机制来静态调用请求对象的方法(注意use引入的类库区别)。

<?phpnamespace app\test\controller;use think\facade\Request;
class Index {
public function index(){ return Request::param('name'); }}

5、助手函数(有无继承都可)

为了简化调用,系统还提供了request助手函数,可以在任何需要的时候直接调用当前请求对象。

<?phpnamespace app\test\controller;
class Index{ public function index(){ return request()->param('name'); }}

请求信息

Request对象支持获取当前的请求信息,包括:

方法

含义

host

当前访问域名或者IP

scheme

当前访问协议

port

当前访问的端口

remotePort

当前请求的REMOTE_PORT

protocol

当前请求的SERVER_PROTOCOL

contentType

当前请求的CONTENT_TYPE

domain

当前包含协议的域名

subDomain

当前访问的子域名

panDomain

当前访问的泛域名

rootDomain

当前访问的根域名(V5.1.6+)

url

当前完整URL

baseUrl

当前URL(不含QUERY_STRING)

query

当前请求的QUERY_STRING参数

baseFile

当前执行的文件

root

URL访问根地址

rootUrl

URL访问根目录

pathinfo

当前请求URL的pathinfo信息(含URL后缀)

path

请求URL的pathinfo信息(不含URL后缀)

ext

当前URL的访问后缀

time

获取当前请求的时间

type

当前请求的资源类型

method

当前请求类型

对于上面的这些请求方法,一般调用无需任何参数,但某些方法可以传入true参数,表示获取带域名的完整地址,例如:

use think\facade\Request;
// 获取完整URL地址 不带域名Request::url();// 获取完整URL地址 包含域名Request::url(true);// 获取当前URL(不含QUERY_STRING) 不带域名Request::baseFile();// 获取当前URL(不含QUERY_STRING) 包含域名Request::baseFile(true);// 获取URL访问根地址 不带域名Request::root();// 获取URL访问根地址 包含域名Request::root(true);

获取完整URL,不带域名

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ return Request::url(); }}

请求变量

可以通过Request对象完成全局输入变量的检测、获取和安全过滤,支持包括$_GET、$_POST、$_REQUEST、$_SERVER、$_SESSION、$_COOKIE、$_ENV等系统变量,以及文件上传信息。(所有示例代码均使用Facade方式)

use think\facade\Request;

1、使用 has() 方法,可以检测全局变量是否已经设置

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ dump(Request::has('name','get')); dump(Request::has('id','post')); }}

2、变量获取

变量获取使用\think\Request类的如下方法及参数:

变量类型方法('变量名/变量修饰符','默认值','过滤方法')

变量类型方法包括:

方法

描述

param

获取当前请求的变量

get

获取 $_GET 变量

post

获取 $_POST 变量

put

获取 PUT 变量

delete

获取 DELETE 变量

session

获取 $_SESSION 变量

cookie

获取 $_COOKIE 变量

request

获取 $_REQUEST 变量

server

获取 $_SERVER 变量

env

获取 $_ENV 变量

route

获取 路由(包括PATHINFO) 变量

file

获取 $_FILES 变量

获取当前强求变量

// 获取当前请求的name变量(过滤)Request::param('name');// 获取当前请求的所有变量(过滤)Request::param();// 获取当前请求的所有变量(原始数据、不过滤)Request::param(false);// 获取当前请求的所有变量(包含上传文件、过滤)Request::param(true);

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ dump(Request::param()); }}

3、变量过滤

框架默认没有设置任何全局过滤规则,可以在应用配置文件中设置全局的过滤规则:

# config/app.php
// 默认全局过滤方法 用逗号分隔多个'default_filter' => 'htmlspecialchars',如果设置过滤方法,上传变量信息会获取不到
# 单个设置dump(Request::param('name','','htmlspecialchars'));

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ dump(Request::param('name','','htmlspecialchars')); }}

php7.3没成功,换成了7.4

4、获取部分变量(only)

只获取当前请求的name变量

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ // 只获取当前请求的name变量 dump(Request::only('name')); //数组形式 //dump(Request::only(['name'])); }}

except排除某些变量后获取

dump(Request::except('id'));//数组形式dump(Request::except(['id']));

5、默认值

Request::get('name'); // 返回值为nullRequest::get('name',''); // 返回值为空字符串Request::get('name','default'); // 返回值为default

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ dump(Request::param('name','Sentiment')); dump(Request::param('name')); dump(Request::param('name','default'));
}}

6、变量修饰符

Request::变量类型('变量名/修饰符');

/s(字符串) /d(整型) /b(布尔) /a(数组) /f(浮点)

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ dump(Request::param('name/s')); dump(Request::param('name/d')); dump(Request::param('name/a'));
}}

7、路由获取

//test/controller/index<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index($id){ dump(Request::route()); }}
//route/route.phpRoute::get('route/:id','test/Index/index');

8、助手函数

为了简化使用,还可以使用系统提供的input助手函数完成上述大部分功能。

  • 判断变量是否定义

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ //get dump(input('?get.name')); //post dump(input('?post.name')); }}

  • 获取PARAM参数

dump(input('param.name')); // 获取单个参数dump(input('param.')); // 获取全部参数// 下面是等效的dump(input('name'));dump(input(''));

  • 获取GET参数

// 获取单个变量dump(input('get.id'));// 使用过滤方法获取 默认为空字符串dump(input('get.name'));// 获取全部变量dump(input('get.'));

  • 使用过滤方法

dump(input('get.name','','htmlspecialchars')); // 获取get变量 并用htmlspecialchars函数过滤dump(input('username','','strip_tags')); // 获取param变量 并用strip_tags函数过滤dump(input('post.name','','org\Filter::safeHtml')); // 获取post变量 并用org\Filter类的safeHtml方法过滤
  • 使用变量修饰符

input('get.id/d');input('post.name/s');input('post.ids/a');

HTTP信息

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ $info = Request::header(); dump($info); dump($info['host']); dump($info['user-agent']); }}

伪静态

URL伪静态通常是为了满足更好的SEO效果,ThinkPHP支持伪静态URL设置,可以通过设置url_html_suffix参数随意在URL的最后增加你想要的静态后缀,而不会影响当前操作的正常执行。

可以通过ext()方法获取后缀

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ return Request::ext(); }
}

当访问index.pdf后会报错,但访问index.html则不会

这是因为在配置文件中设置的伪静态为html,若想用pdf,通过|分割加上即可

'url_html_suffix'        => 'html|pdf',

在不该设置的情况下,使用 url::build() 获取当前完整 url,得到默认后缀为 .html

<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ return \think\facade\Url::build(); }
}

若不想使用伪静态关闭即可

'url_html_suffix' => false,

参数绑定

1、默认参数

<?phpnamespace app\test\controller;class Index{ public function index($name='Sentiment',$id=1){ return 'name:'.$name.'<br>'.'id:'.$id; }}

2、成对解析,可以换顺序

// URL参数方式 0 按名称成对解析 1 按顺序解析'url_param_type' => 0,

请求缓存

全局缓存

// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则'request_cache' => false,// 请求缓存有效期,建议3600,时间太短没有意义'request_cache_expire' => null,
// 全局请求缓存排除规则'request_cache_except' => [],

开启缓存后,第二次访问时,会自动获取请求缓存的数据响应输出,并发送304状态码

单独缓存

//route/route.phpRoute::get('route/:id','test/Index/index')->cache(3600);//test/controller/index.php<?phpnamespace app\test\controller;use think\facade\Request;class Index{ public function index(){ dump(Request::param()); dump(Request::route()); }}

刷新一次后状态码变成304,这时就已经缓存了,当我改变index.php的内容后,访问/route/777仍然是这个界面


响应

响应(Response)对象用于动态响应客户端请求,控制发送给用户的信息。通常用于输出数据给客户端或者浏览器。由think\Response类或者子类完成。

响应参数

响应输出,包括 return(),json(),view()

<?phpnamespace app\test\controller;class Index{ public function response(){ return response('index','201'); //return response('index')->code('201'); //设置头信息 //return response('index')->code('201')->header(['Cache-control' => 'no-cache,must-revalidate']); sh }
}

重定向

redirect() 方法页面重定向

<?phpnamespace app\test\controller;class Index{ public function response(){ return redirect('http://sentiment1.top'); }}

站内重定向,直接输入路由地址或相对地址即可

return redirect('/index/index/hello/name/Sentiment');
return redirect('hello')->params(['name'=>'Sentiment']);
return redirect('hello',['name'=>'Sentiment']);

文件下载

文本文件和图片文件都可以使用 download() 方法下载

<?phpnamespace app\test\controller;class Index{ public function down(){ $data='this is test'; return download($data,'test.txt',true); }}

访问/test/index/down后便可下载test.txt,内容为this is test


往期推荐



原创 | Http Request-Smuggling

原创 | 从PHP反序列化原理到POP链构造

原创 | phar反序列化学习


继续滑动看下一个
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存